package com.gnuc.thoth.service.listeners;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.TimeZone;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.ContentValues;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.gnuc.thoth.framework.Thoth;
import com.gnuc.thoth.framework.Thoth.REQ;
import com.gnuc.thoth.framework.ThothLog;
import com.gnuc.thoth.framework.ThothMail;
import com.gnuc.thoth.framework.callbacks.ThothMailCallback;
import com.gnuc.thoth.framework.callbacks.ThothRequestCallback;
import com.gnuc.thoth.framework.db.ThothDB;

public class RequestListener
{
	public static void onReceive(int reqCode, final ThothRequestCallback reqCallback)
	{
		final DefaultHttpClient client = Thoth.client;
		switch (reqCode)
		{
			case REQ.HELLO :
			{
				Runnable rHELLO = new Runnable()
				{
					@Override
					public void run()
					{
						try
						{
							BasicHttpParams params = new BasicHttpParams();
							SchemeRegistry schemeRegistry = new SchemeRegistry();
							schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
							final SSLSocketFactory sslSocketFactory = SSLSocketFactory.getSocketFactory();
							schemeRegistry.register(new Scheme("https", sslSocketFactory, 443));
							ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
							DefaultHttpClient tmpClient = new DefaultHttpClient(cm, params);
							HttpResponse resp = tmpClient.execute(new HttpGet(REQ.SERVER + "/hello"));
							String respStr = EntityUtils.toString(resp.getEntity());
							int respCode = resp.getStatusLine().getStatusCode();
							if (respCode == HttpURLConnection.HTTP_OK)
								reqCallback.handle(1);
							else
								throw new Exception(respStr);
						}
						catch (IOException e)
						{}
						catch (Exception e)
						{
							ThothLog.e(e);
							reqCallback.handle(-1);
						}
					}
				};
				performOnBackgroundThread(rHELLO);
				break;
			}
			case REQ.CONNECT :
			{
				Runnable rCONNECT = new Runnable()
				{
					@Override
					public void run()
					{
						try
						{
							HttpPost req = new HttpPost(REQ.SERVER + "/login");
							JSONObject jo = new JSONObject();
							jo.put("ACTION", "USR_CONNECT");
							req.setEntity(new StringEntity(jo.toString(), "UTF-8"));
							req.setHeader("Accept", "application/json");
							req.setHeader("Content-type", "application/json");
							req.setHeader("Accept-Encoding", "gzip");
							HttpResponse resp = client.execute(req);
							String respStr = EntityUtils.toString(resp.getEntity());
							int respCode = resp.getStatusLine().getStatusCode();
							if (respCode == HttpURLConnection.HTTP_OK && Thoth.auth.equalsIgnoreCase(respStr))
								reqCallback.handle(1);
							else
								throw new Exception(respStr);
						}
						catch (IOException e)
						{}
						catch (Exception e)
						{
							ThothLog.e(e);
							reqCallback.handle(-1);
						}
					}
				};
				performOnBackgroundThread(rCONNECT);
				break;
			}
			case REQ.USR_CHECK :
			{
				Runnable rUSR_CHECK = new Runnable()
				{
					@Override
					public void run()
					{
						try
						{
							HttpPost req = new HttpPost(REQ.SERVER + "/user");
							JSONObject jo = new JSONObject();
							JSONObject joo = new JSONObject();
							joo.put("ACCOUNT", Thoth.Settings.USR_DEVICE_ACCOUNT_EMAIL);
							jo.put("USER_DATA", joo);
							jo.put("AUTH", Thoth.auth);
							jo.put("ACTION", "USR_CHECK");
							req.setEntity(new StringEntity(jo.toString(), "UTF-8"));
							req.setHeader("Accept", "application/json");
							req.setHeader("Content-type", "application/json");
							req.setHeader("Accept-Encoding", "gzip");
							HttpResponse resp = client.execute(req);
							String respStr = EntityUtils.toString(resp.getEntity());
							int respCode = resp.getStatusLine().getStatusCode();
							if (respCode == HttpURLConnection.HTTP_OK)
								reqCallback.handle(1); // User exists
							else if (respCode == HttpURLConnection.HTTP_NOT_FOUND)
								reqCallback.handle(2); // User does not exist
							else
								throw new Exception(respStr);
						}
						catch (IOException e)
						{}
						catch (Exception e)
						{
							ThothLog.e(e);
							reqCallback.handle(-1);
						}
					}
				};
				performOnBackgroundThread(rUSR_CHECK);
				break;
			}
			case REQ.USR_CREATE :
			{
				Runnable rUSR_CREATE = new Runnable()
				{
					@Override
					public void run()
					{
						try
						{
							HttpPost req = new HttpPost(REQ.SERVER + "/user");
							// Build response
							JSONObject jo = new JSONObject();
							JSONObject joo = new JSONObject();
							JSONObject jooo = new JSONObject();
							jooo.put("dBM", Thoth.Settings.USR_DEVICE_BUILD_MODEL);
							jooo.put("dIMEI", Thoth.Settings.USR_DEVICE_IMEI);
							jooo.put("dBF", Thoth.Settings.USR_DEVICE_BUILD_FIRMWARE);
							jooo.put("dPN", Thoth.Settings.USR_DEVICE_PHONE_NUMBER);
							joo.put("DEVICE_DATA", jooo);
							joo.put("ACCOUNT", Thoth.Settings.USR_DEVICE_ACCOUNT_EMAIL);
							jo.put("USER_DATA", joo);
							jo.put("AUTH", Thoth.auth);
							jo.put("ACTION", "USR_CREATE");
							// Set response
							req.setEntity(new StringEntity(jo.toString(), "UTF-8"));
							req.setHeader("Accept", "application/json");
							req.setHeader("Content-type", "application/json");
							req.setHeader("Accept-Encoding", "gzip");
							HttpResponse resp = client.execute(req);
							String respStr = EntityUtils.toString(resp.getEntity());
							int respCode = resp.getStatusLine().getStatusCode();
							if (respCode == HttpURLConnection.HTTP_OK)
								reqCallback.handle(1); // User create OK
							else if (respCode == HttpURLConnection.HTTP_FORBIDDEN)
								reqCallback.handle(2); // User already exists
							else
								throw new Exception(respStr);
						}
						catch (IOException e)
						{}
						catch (Exception e)
						{
							ThothLog.e(e);
							reqCallback.handle(-1);
						}
					}
				};
				performOnBackgroundThread(rUSR_CREATE);
				break;
			}
			case REQ.USR_EDIT :
			{
				Runnable rUSR_EDIT = new Runnable()
				{
					@Override
					public void run()
					{
						try
						{
							HttpPost req = new HttpPost(REQ.SERVER + "/user");
							// Build response
							JSONObject jo = new JSONObject();
							JSONObject joo = new JSONObject();
							JSONObject jooo = new JSONObject();
							jooo.put("dBM", Thoth.Settings.USR_DEVICE_BUILD_MODEL);
							jooo.put("dIMEI", Thoth.Settings.USR_DEVICE_IMEI);
							jooo.put("dBF", Thoth.Settings.USR_DEVICE_BUILD_FIRMWARE);
							jooo.put("dPN", Thoth.Settings.USR_DEVICE_PHONE_NUMBER);
							joo.put("DEVICE_DATA", jooo);
							joo.put("ACCOUNT", Thoth.Settings.USR_DEVICE_ACCOUNT_EMAIL);
							jo.put("USER_DATA", joo);
							jo.put("AUTH", Thoth.auth);
							jo.put("ACTION", "USR_EDIT");
							req.setEntity(new StringEntity(jo.toString(), "UTF-8"));
							req.setHeader("Accept", "application/json");
							req.setHeader("Content-type", "application/json");
							req.setHeader("Accept-Encoding", "gzip");
							HttpResponse resp = client.execute(req);
							String respStr = EntityUtils.toString(resp.getEntity());
							int respCode = resp.getStatusLine().getStatusCode();
							if (respCode == HttpURLConnection.HTTP_OK)
								reqCallback.handle(1); // Added new device to user
							else if (respCode == HttpURLConnection.HTTP_CONFLICT)
								reqCallback.handle(1); // Device already exists
							else
								throw new Exception(respStr);
						}
						catch (IOException e)
						{}
						catch (Exception e)
						{
							ThothLog.e(e);
							reqCallback.handle(-1);
						}
					}
				};
				performOnBackgroundThread(rUSR_EDIT);
				break;
			}
			case REQ.LOG_CREATE :
			{
				Runnable rLOG_CREATE = new Runnable()
				{
					@Override
					public void run()
					{
						boolean success = false;
						boolean isCallLog = false, isMsgsLog = false, isDataLog = false, isWifiLog = false, isMoblLog = false;
						Cursor cR = null;
						final ThothDB dbA = new ThothDB(Thoth.cx);
						HashMap<String, JSONArray> map = new HashMap<String, JSONArray>();
						dbA.open();
						try
						{
							int timeZone = TimeZone.getDefault().getRawOffset();
							SQLiteDatabase db = dbA.getDb();
							cR = db.rawQuery("SELECT * FROM " + ThothDB.table_TEMP_CALL + " ORDER BY " + ThothDB.col_T_C_CONTACT + " ASC", null);
							JSONArray callL = new JSONArray();
							if (cR != null && cR.moveToFirst())
							{
								JSONObject ci = null;
								JSONArray ci_cl = null;
								String prevContact = "";
								reqCallback.progress(-50, cR.getCount(), 0);
								for (int x = 0,y=x; x < cR.getCount(); x++,y++)
								{
									String currContact = cR.getString(cR.getColumnIndexOrThrow(ThothDB.col_T_C_CONTACT));
									if (prevContact.equalsIgnoreCase(currContact))
									{
										JSONObject cli = new JSONObject();
										cli.put("tyOf", cR.getInt(cR.getColumnIndexOrThrow(ThothDB.col_T_C_TYPE)));
										cli.put("tiOf", cR.getLong(cR.getColumnIndexOrThrow(ThothDB.col_T_C_DATETIME)));
										cli.put("tZOf", timeZone);
										cli.put("dOf", cR.getLong(cR.getColumnIndexOrThrow(ThothDB.col_T_C_DURATION)));
										ci_cl.put(cli);
									}
									else
									{
										if (null == ci && null == ci_cl)
										{
											ci = new JSONObject();
											ci_cl = new JSONArray();
										}
										else
										{
											ci.put("cL", ci_cl);
											callL.put(ci);
											
											if(y>150)
											{
												map.put("CALL$"+x,callL);
												callL= new JSONArray();
												y=0;
											}
											ci = new JSONObject();
											ci_cl = new JSONArray();
										}
										ci.put("cRId", currContact);
										ci.put("cN", cR.getString(cR.getColumnIndexOrThrow(ThothDB.col_T_C_CONTACTNAME)));
										ci.put("cPN", cR.getString(cR.getColumnIndexOrThrow(ThothDB.col_T_C_NUMBER)));
										ci.put("cE", "");
										JSONObject cli = new JSONObject();
										cli.put("tyOf", cR.getInt(cR.getColumnIndexOrThrow(ThothDB.col_T_C_TYPE)));
										cli.put("tiOf", cR.getLong(cR.getColumnIndexOrThrow(ThothDB.col_T_C_DATETIME)));
										cli.put("tZOf", timeZone);
										cli.put("dOf", cR.getLong(cR.getColumnIndexOrThrow(ThothDB.col_T_C_DURATION)));
										ci_cl.put(cli);
									}
									prevContact = currContact;
									cR.moveToNext();
									if (cR.getCount() > 0 && cR.getCount() < 2)
									{
										ci.put("cL", ci_cl);
										callL.put(ci);
									}
									reqCallback.progress(cR.getCount(), 1, 0);
								}
								isCallLog = true;
							}
							else
								isCallLog = false;
							if (null != cR && !cR.isClosed())
								cR.close();
							// SMS and MMS messages to JSON
							JSONArray msgsL = new JSONArray();
							cR = db.rawQuery("SELECT * FROM " + ThothDB.table_TEMP_MSGS + " ORDER BY " + ThothDB.col_T_M_CONTACT + " ASC", null);
							if (cR != null && cR.moveToFirst())
							{
								JSONObject mi = null;
								JSONArray mi_ml = null;
								String prevContact = "";
								reqCallback.progress(-50, cR.getCount(), 0);
								for (int x = 0,y=x; x < cR.getCount(); x++,y++)
								{
									String currContact = cR.getString(cR.getColumnIndexOrThrow(ThothDB.col_T_M_CONTACT));
									if (prevContact.equalsIgnoreCase(currContact))
									{
										JSONObject mli = new JSONObject();
										mli.put("tyOf", cR.getInt(cR.getColumnIndexOrThrow(ThothDB.col_T_M_TYPE)));
										mli.put("tiOf", cR.getLong(cR.getColumnIndexOrThrow(ThothDB.col_T_M_DATETIME)));
										mli.put("tZOf", timeZone);
										mli.put("bOf", cR.getString(cR.getColumnIndexOrThrow(ThothDB.col_T_M_MSG)));
										mi_ml.put(mli);
									}
									else
									{
										if (null == mi && null == mi_ml)
										{
											mi = new JSONObject();
											mi_ml = new JSONArray();
										}
										else
										{
											mi.put("mL", mi_ml);
											msgsL.put(mi);
											if(y>150)
											{
												map.put("MSGS$"+x,msgsL);
												msgsL= new JSONArray();
												y=0;
											}
											mi = new JSONObject();
											mi_ml = new JSONArray();
										}
										mi = new JSONObject();
										mi_ml = new JSONArray();
										mi.put("cRId", currContact);
										mi.put("cN", cR.getString(cR.getColumnIndexOrThrow(ThothDB.col_T_M_CONTACTNAME)));
										mi.put("cPN", cR.getString(cR.getColumnIndexOrThrow(ThothDB.col_T_M_NUMBER)));
										mi.put("cE", "");
										JSONObject mli = new JSONObject();
										mli.put("tyOf", cR.getInt(cR.getColumnIndexOrThrow(ThothDB.col_T_M_TYPE)));
										mli.put("tiOf", cR.getLong(cR.getColumnIndexOrThrow(ThothDB.col_T_M_DATETIME)));
										mli.put("tZOf", timeZone);
										mli.put("bOf", cR.getString(cR.getColumnIndexOrThrow(ThothDB.col_T_M_MSG)));
										mi_ml.put(mli);
									}
									prevContact = currContact;
									cR.moveToNext();
									if (cR.getCount() > 0 && cR.getCount() < 2)
									{
										mi.put("mL", mi_ml);
										msgsL.put(mi);
									}
									reqCallback.progress(cR.getCount(), 1, 0);
								}
								isMsgsLog = true;
							}
							else
								isMsgsLog = false;
							if (null != cR && !cR.isClosed())
								cR.close();
							// Data logs
							JSONArray appsL = new JSONArray();
							cR = db.rawQuery("SELECT SUM(" + ThothDB.col_T_A_UPLOAD + "),SUM(" + ThothDB.col_T_A_DOWNLOAD + ")," + ThothDB.col_T_A_DAYID + ", " + ThothDB.col_T_A_PKG + ", " + ThothDB.col_T_A_NAME + ", " + ThothDB.col_T_A_UID + " FROM " + ThothDB.table_TEMP_APPS + " GROUP BY " + ThothDB.col_T_A_PKG + ", " + ThothDB.col_T_A_DAYID, null);
							if (cR != null && cR.moveToFirst())
							{
								JSONObject ai = null;
								JSONArray ai_al = null;
								String prevApp = "";
								reqCallback.progress(-50, cR.getCount(), 0);
								for (int x = 0; x < cR.getCount(); x++)
								{
									String currApp = cR.getString(3);
									if (prevApp.equalsIgnoreCase(currApp))
									{
										JSONObject ali = new JSONObject();
										ali.put("tiOf", cR.getLong(2));
										ali.put("uL", cR.getLong(0));
										ali.put("dL", cR.getLong(1));
										ai_al.put(ali);
									}
									else
									{
										if (null == ai && null == ai_al)
										{
											ai = new JSONObject();
											ai_al = new JSONArray();
										}
										else
										{
											ai.put("aL", ai_al);
											appsL.put(ai);
											ai = new JSONObject();
											ai_al = new JSONArray();
										}
										ai = new JSONObject();
										ai_al = new JSONArray();
										ai.put("aP", currApp);
										ai.put("aN", cR.getString(4));
										ai.put("aUID", cR.getInt(5));
										JSONObject ali = new JSONObject();
										ali.put("tiOf", cR.getLong(2));
										ali.put("uL", cR.getLong(0));
										ali.put("dL", cR.getLong(1));
										ai_al.put(ali);
									}
									prevApp = currApp;
									cR.moveToNext();
									if (cR.getCount() > 0 && cR.getCount() < 2)
									{
										ai.put("aL", ai_al);
										appsL.put(ai);
									}
									reqCallback.progress(cR.getCount(), 1, 0);
								}
								isDataLog = true;
							}
							else
								isDataLog = false;
							if (null != cR && !cR.isClosed())
								cR.close();
							// Device Data logs
							JSONArray wifiL = new JSONArray();
							cR = db.rawQuery("SELECT " + ThothDB.col_T_D_W_BOOTID + ", " + ThothDB.col_T_D_W_UPLOAD + ", " + ThothDB.col_T_D_W_DOWNLOAD + " FROM " + ThothDB.table_TEMP_DATA_WIFI + " WHERE (" + ThothDB.col_T_D_W_UPLOAD + "+" + ThothDB.col_T_D_W_DOWNLOAD + ")>0", null);
							if (cR != null && cR.moveToFirst())
							{
								reqCallback.progress(-50, cR.getCount(), 0);
								for (int x = 0; x < cR.getCount(); x++)
								{
									JSONObject wli = new JSONObject();
									wli.put("tiOf", cR.getLong(0));
									wli.put("uL", cR.getLong(1));
									wli.put("dL", cR.getLong(2));
									wifiL.put(wli);
									cR.moveToNext();
									reqCallback.progress(cR.getCount(), 1, 0);
								}
							}
							else
								isWifiLog = false;
							if (null != cR && !cR.isClosed())
								cR.close();
							JSONArray moblL = new JSONArray();
							cR = db.rawQuery("SELECT " + ThothDB.col_T_D_M_BOOTID + ", " + ThothDB.col_T_D_M_UPLOAD + ", " + ThothDB.col_T_D_M_DOWNLOAD + " FROM " + ThothDB.table_TEMP_DATA_MOBL + " WHERE (" + ThothDB.col_T_D_M_UPLOAD + "+" + ThothDB.col_T_D_M_DOWNLOAD + ")>0", null);
							if (cR != null && cR.moveToFirst())
							{
								reqCallback.progress(-50, cR.getCount(), 0);
								for (int x = 0; x < cR.getCount(); x++)
								{
									JSONObject mli = new JSONObject();
									mli.put("tiOf", cR.getLong(0));
									mli.put("uL", cR.getLong(1));
									mli.put("dL", cR.getLong(2));
									moblL.put(mli);
									cR.moveToNext();
									reqCallback.progress(cR.getCount(), 1, 0);
								}
								isMoblLog = true;
							}
							else
								isMoblLog = false;
							if (null != cR && !cR.isClosed())
								cR.close();
							// ///////////////////////////
							if (isCallLog || isMsgsLog || isDataLog || isWifiLog || isMoblLog)
							{
								int successCnt = 0;
								map.put("APPS", appsL);
								map.put("MOBL", moblL);
								map.put("WIFI", wifiL);
								reqCallback.progress(-50, map.size()*10, 0);
								for (String key : map.keySet().toArray(new String[map.size()]))
								{
									JSONObject jo = new JSONObject();
									JSONObject joo1 = new JSONObject();
									JSONObject joo2 = new JSONObject();
									joo1.put(key.indexOf("$")>-1?key.substring(0,key.indexOf("$")):key, map.get(key));
									joo2.put("DEVICE", Thoth.Settings.USR_DEVICE_PHONE_NUMBER);
									joo2.put("ACCOUNT", Thoth.Settings.USR_DEVICE_ACCOUNT_EMAIL);
									jo.put("USER_DATA", joo2);
									jo.put("LOG_DATA", joo1);
									jo.put("AUTH", Thoth.auth);
									jo.put("ACTION", "LOG_CREATE");
									try
									{
										HttpPost req = new HttpPost(REQ.SERVER + "/logger");
										req.setHeader("Accept", "application/json");
										req.setHeader("Content-type", "application/json");
										req.setHeader("Accept-Encoding", "gzip");
										req.setEntity(new StringEntity(jo.toString(), "UTF-8"));
										ThothLog.backupSend(jo.toString(), "LOG_CREATE_" + key);
										HttpResponse resp = client.execute(req);
										String respStr = EntityUtils.toString(resp.getEntity());
										int respCode = resp.getStatusLine().getStatusCode();
										if (respCode == HttpURLConnection.HTTP_OK)
											++successCnt;
										else
											throw new Exception(null != respStr && respStr.length() > 0 ? respStr : respCode + " : Empty response.");
										reqCallback.progress(50, 10, 0);
									}
									catch (Exception e)
									{
										throw e;
									}
								}
								if (successCnt > 0)
								{
									success = true;
									map.clear();
								}
								else
									throw new Exception("Noting was logged to server.");
							}
							else
								reqCallback.handle(4);
							if (db.isOpen())
								db.close();
						}
						catch (Exception e)
						{
							ThothLog.e(e);
							reqCallback.handle(-1);
						}
						finally
						{
							if (null != cR && !cR.isClosed())
								cR.close();
							reqCallback.progress(50, 25, 0);
							if (success)
							{
								if (isMsgsLog && Thoth.Settings.APP_ENABLE_GoMAIL)
								{
									ThothMail.getInstance().sendMail(new ThothMailCallback()
									{
										@Override
										public void handle(boolean result, int resultCode)
										{}
										
										@Override
										public void progress(int resultCode, int progressValue)
										{}
									});
								}
								if (!dbA.getDb().isOpen())
									dbA.open();
								dbA.refreshTempTables(dbA.getDb());
								reqCallback.handle(1);
								if (dbA.getDb().isOpen())
									dbA.close();
							}
							reqCallback.progress(50, 50, 0);
						}
					}
				};
				performOnBackgroundThread(rLOG_CREATE);
				break;
			}
			case REQ.LOG_ANALYTICS :
			{
				Runnable rLOG_ANALYTICS = new Runnable()
				{
					@Override
					public void run()
					{
						int successCnt;
						JSONObject rjo = null;
						HashMap<String, JSONObject> map = new HashMap<String, JSONObject>();
						map.put("CALL", null);
						map.put("MSGS", null);
						map.put("MSGM", null);
						map.put("DATA", null);
						reqCallback.progress(-50, 200, 0);
						successCnt = 0;
						for (String key : map.keySet().toArray(new String[4]))
						{
							boolean subSuccess = false;
							JSONObject respJSON = null;
							try
							{
								HttpPost req = new HttpPost(REQ.SERVER + "/logger");
								JSONObject jo = new JSONObject();
								JSONObject joo = new JSONObject();
								JSONObject jooo = new JSONObject();
								jooo.put("dPN", Thoth.Settings.USR_DEVICE_PHONE_NUMBER);
								joo.put("DEVICE_DATA", jooo);
								joo.put("ACCOUNT", Thoth.Settings.USR_DEVICE_ACCOUNT_EMAIL);
								jo.put("USER_DATA", joo);
								jo.put("AUTH", Thoth.auth);
								jo.put("ACTION", "LOG_ANALYTICS");
								jo.put("SUB_ACTION", key);
								req.setHeader("Accept", "application/json");
								req.setHeader("Content-type", "application/json");
								req.setHeader("Accept-Encoding", "gzip");
								req.setEntity(new StringEntity(jo.toString(), "UTF-8"));
								HttpResponse resp = client.execute(req);
								reqCallback.progress(50, 25, 0);
								String respStr = EntityUtils.toString(resp.getEntity());
								int respCode = resp.getStatusLine().getStatusCode();
								if (respCode == HttpURLConnection.HTTP_OK && respStr.length() > 0)
								{
									subSuccess = true;
									respJSON = new JSONObject(respStr);
								}
								else
									throw new Exception(null != respStr && respStr.length() > 0 ? respStr : respCode + " : Empty response.");
							}
							catch (IOException e1)
							{}
							catch (Exception e)
							{
								ThothLog.e(e);
								subSuccess = false;
							}
							finally
							{
								reqCallback.progress(50, 50, 0);
								if (subSuccess && null != respJSON)
								{
									try
									{
										if (respJSON.has("LOG_DATA"))
										{
											JSONObject jo = respJSON.getJSONObject("LOG_DATA");
											if (null != jo && jo.has(key))
											{
												map.put(key, jo.getJSONObject(key));
												successCnt++;
											}
										}
										else
											throw new Exception("Response : " + key + " did not have any Log data.");
									}
									catch (Exception e)
									{
										ThothLog.e(e);
									}
								}
							}
						}
						if (successCnt == 4)
						{
							rjo = new JSONObject();
							try
							{
								rjo.put("ACTION", "LOG_ANALYTICS");
								JSONObject joo = new JSONObject();
								for (String key : map.keySet().toArray(new String[4]))
									joo.put(key, map.get(key));
								rjo.put("LOG_DATA", joo);
								ThothLog.backupSend(rjo.toString(), "LOG_ANALYTICS");
								processJSON(rjo); // Update the app tables.
								reqCallback.handle(1);
							}
							catch (JSONException e)
							{
								ThothLog.e(e);
								reqCallback.handle(-1);
							}
						}
						else
						{
							ThothLog.e(new Exception("Only found " + successCnt));
							reqCallback.handle(-1);
						}
					}
				};
				performOnBackgroundThread(rLOG_ANALYTICS);
				break;
			}
		}
	}
	
	private static Thread performOnBackgroundThread(final Runnable runnable)
	{
		final Thread t = new Thread()
		{
			@Override
			public void run()
			{
				try
				{
					runnable.run();
				}
				finally
				{}
			}
		};
		t.start();
		return t;
	}
	
	static boolean processJSON(JSONObject jo)
	{
		boolean status = false;
		ThothDB dbA = new ThothDB(Thoth.cx);
		dbA.open();
		SQLiteDatabase db = dbA.getDb();
		try
		{
			dbA.refreshRankTables(db);
			dbA.refreshStatsTables(db);
			JSONObject joo = jo.getJSONObject("LOG_DATA");
			HashMap<Integer, String> map = new HashMap<Integer, String>();
			map.put(0, "TODAY");
			map.put(1, "THIS_WEEK");
			map.put(2, "LAST_WEEK");
			map.put(3, "THIS_MONTH");
			map.put(4, "LAST_MONTH");
			map.put(5, "THIS_YEAR");
			// Process CALL
			JSONObject jCALL = joo.getJSONObject("CALL");
			JSONObject jMSGS = joo.getJSONObject("MSGS");
			JSONObject jMSGM = joo.getJSONObject("MSGM");
			JSONObject jDATA = joo.getJSONObject("DATA");
			for (int key : map.keySet().toArray(new Integer[6]))
			{
				JSONObject jFC = jCALL.getJSONObject(map.get(key));
				ContentValues nR = new ContentValues();
				nR.put(ThothDB.col_A_S_C_FILTER, key);
				nR.put(ThothDB.col_A_S_C_TOTAL_OUTBOUND_CALLS, jFC.has("dPC") ? jFC.getLong("dPC") : 0);
				nR.put(ThothDB.col_A_S_C_TOTAL_INBOUND_CALLS, jFC.has("dReC") ? jFC.getLong("dReC") : 0);
				nR.put(ThothDB.col_A_S_C_TOTAL_PLACED_CALLS, jFC.has("tPC") ? jFC.getLong("tPC") : 0);
				nR.put(ThothDB.col_A_S_C_TOTAL_RECEIVED_CALLS, jFC.has("tReC") ? jFC.getLong("tReC") : 0);
				nR.put(ThothDB.col_A_S_C_TOTAL_MISSED_CALLS, jFC.has("tMC") ? jFC.getLong("tMC") : 0);
				// nR.put(ThothDB.col_A_S_C_TOTAL_REJECTED_CALLS, jF.has("tRjC") ?
				// jF.getLong("tRjC") : 0);
				// nR.put(ThothDB.col_A_S_C_TOTAL_NOANSWER_CALLS, jF.has("tNC") ?
				// jF.getLong("tNC") : 0);
				db.insertOrThrow(ThothDB.table_APP_CALL_STAT, "", nR);
				int x = 0;
				for (String r : new String[]{"topPlaced", "topRecieved"})
				{
					JSONArray jFA = jFC.getJSONArray(r);
					nR = new ContentValues();
					for (int l = 0; l < jFA.length(); ++l)
					{
						JSONObject jFAI = jFA.getJSONObject(l);
						// String contactPos = jFAI.getString("cP");
						String contactRefId = jFAI.getString("cR");
						// String contactName = jFAI.getString("cN");
						String contactPhoneNumber = jFAI.getString("cPN");
						String totalDuration = jFAI.getString("tD");
						String times = jFAI.getString("t");
						nR = new ContentValues();
						nR.put(ThothDB.col_A_R_C_FILTER, key);
						nR.put(ThothDB.col_A_R_C_NUMBER, contactPhoneNumber);
						nR.put(ThothDB.col_A_R_C_CONTACT, contactRefId);
						nR.put(ThothDB.col_A_R_C_DURATION, totalDuration);
						nR.put(ThothDB.col_A_R_C_TYPE, x);
						nR.put(ThothDB.col_A_R_C_CONTACTED, times);
						db.insertOrThrow(ThothDB.table_APP_CALL_RANK, "", nR);
					}
					++x;
				}
				JSONObject jFMS = jMSGS.getJSONObject(map.get(key));
				nR = new ContentValues();
				nR.put(ThothDB.col_A_S_C_FILTER, key);
				nR.put(ThothDB.col_A_S_M_TOTAL_OUTBOUND_MSGS, jFMS.has("tSS") ? jFMS.getLong("tSS") : 0);
				nR.put(ThothDB.col_A_S_M_TOTAL_INBOUND_MSGS, jFMS.has("tRS") ? jFMS.getLong("tRS") : 0);
				JSONObject jFMM = jMSGM.getJSONObject(map.get(key));
				nR.put(ThothDB.col_A_S_M_TOTAL_OUTBOUND_MSGM, jFMM.has("tSM") ? jFMM.getLong("tSM") : 0);
				nR.put(ThothDB.col_A_S_M_TOTAL_INBOUND_MSGM, jFMM.has("tRM") ? jFMM.getLong("tRM") : 0);
				db.insertOrThrow(ThothDB.table_APP_MSGS_STAT, "", nR);
				x = 0;
				for (String r : new String[]{"topSentSMS", "topReceivedSMS", "topSentMMS", "topReceivedMMS"})
				{
					JSONArray jFMA = null;
					if (x < 2)
						jFMA = jFMS.has(r) ? jFMS.getJSONArray(r) : new JSONArray();
					else
						jFMA = jFMS.has(r) ? jFMS.getJSONArray(r) : new JSONArray();
					nR = new ContentValues();
					for (int l = 0; l < jFMA.length(); ++l)
					{
						JSONObject jFAI = jFMA.getJSONObject(l);
						// String contactPos = jFAI.getString("cP");
						String contactRefId = jFAI.getString("cR");
						// String contactName = jFAI.getString("cN");
						String contactPhoneNumber = jFAI.getString("cPN");
						String times = jFAI.getString("t");
						nR = new ContentValues();
						nR.put(ThothDB.col_A_R_M_FILTER, key);
						nR.put(ThothDB.col_A_R_M_NUMBER, contactPhoneNumber);
						nR.put(ThothDB.col_A_R_M_CONTACT, contactRefId);
						nR.put(ThothDB.col_A_R_M_CONTACTED, times);
						nR.put(ThothDB.col_A_R_M_TYPE, x);
						db.insertOrThrow(ThothDB.table_APP_MSGS_RANK, "", nR);
					}
					++x;
				}
				JSONObject jFD = jDATA.getJSONObject(map.get(key));
				nR = new ContentValues();
				nR.put(ThothDB.col_A_S_D_FILTER, key);
				nR.put(ThothDB.col_A_S_D_WIFI_UPLOADED_DATA, jFD.has("tWU") ? jFD.getLong("tWU") : 0);
				nR.put(ThothDB.col_A_S_D_WIFI_DOWNLOADED_DATA, jFD.has("tWD") ? jFD.getLong("tWD") : 0);
				nR.put(ThothDB.col_A_S_D_MOBL_UPLOADED_DATA, jFD.has("tMU") ? jFD.getLong("tMU") : 0);
				nR.put(ThothDB.col_A_S_D_MOBL_DOWNLOADED_DATA, jFD.has("tMD") ? jFD.getLong("tMD") : 0);
				db.insertOrThrow(ThothDB.table_APP_DATA_STAT, "", nR);
				x = 0;
				final PackageManager pkgMgr = Thoth.cx.getPackageManager();
				for (String r : new String[]{"topUploader", "topDownloader"})
				{
					JSONArray jFA = jFD.getJSONArray(r);
					nR = new ContentValues();
					for (int l = 0; l < jFA.length(); ++l)
					{
						JSONObject jFAI = jFA.getJSONObject(l);
						String appName = jFAI.getString("aN");
						String appPkg = jFAI.getString("aPkg");
						int appUID = pkgMgr.getApplicationInfo(appPkg, PackageManager.GET_META_DATA).uid;
						String appQuantity = jFAI.getString("aQ");
						nR = new ContentValues();
						nR.put(ThothDB.col_A_R_D_FILTER, key);
						nR.put(ThothDB.col_A_R_D_APP_ID, appUID);
						nR.put(ThothDB.col_A_R_D_APP_NAME, appName);
						if (appName.equalsIgnoreCase("thoth"))
							continue;
						nR.put(ThothDB.col_A_R_D_APP_PACKAGE, appPkg);
						nR.put(ThothDB.col_A_R_D_QUANTITY, appQuantity);
						nR.put(ThothDB.col_A_R_D_TYPE, x);
						db.insertOrThrow(ThothDB.table_APP_DATA_RANK, "", nR);
					}
					++x;
				}
			}
			status = true;
		}
		catch (JSONException e)
		{
			ThothLog.e(e);
		}
		catch (Exception e)
		{
			ThothLog.e(e);
		}
		finally
		{
			if (db.isOpen())
				db.close();
		}
		return status;
	}
	
	public static String kbSizer(double size)
	{
		final double BASE = 1024, KB = BASE, MB = KB * BASE, GB = MB * BASE;
		final DecimalFormat df = new DecimalFormat("#.##");
		return (size >= GB) ? df.format(size / GB) + " GB" : (size >= MB) ? df.format(size / MB) + " MB" : (size >= KB) ? df.format(size / KB) + " KB" : (int) size + " bytes";
	}
}
